package com.sc.core.make.file;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sc.common.response.Response;
import com.sc.core.make.MasterMake;
import com.sc.core.make.build.*;
import com.sc.core.make.dto.MakeInfoDTO;
import com.sc.core.util.DataAutoSearch.DataAutoSearch;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class Controller implements IFileMake{
    private final MakeInfoDTO makeInfo;
    private final Map<String, Map<Integer, String>> enumMap;

    @Getter
    private String message = "成功";

    public Controller(MakeInfoDTO makeInfo, Map<String, Map<Integer, String>> enumMap) {
        this.makeInfo = makeInfo;
        this.enumMap = enumMap;
    }

    @Override
    public Controller make() {
        ClassBuild classBuild = new ClassBuild(makeInfo.getClassname() + "Controller");
        classBuild.setPackageName(makeInfo.getPackageName() + ".controller");
        classBuild.setDocument(new String[]{makeInfo.getTableComment() + "控制器"});

        annotationHandle(classBuild);

        String serviceClassname = String.format("I%sService", makeInfo.getClassname());
        PropertyBuild service = new PropertyBuild(
                String.format("%sService", makeInfo.getIdentity()),
                new GenericTypeBuild(serviceClassname)
        );
        service.setFinal(true);
        classBuild.addImportClass(makeInfo.getPackageName() + ".service." + serviceClassname);
        classBuild.addProperty(service);

        methodHandle(classBuild);

        MasterMake.writeFile(MasterMake.getMakeDir(makeInfo.getModuleName()) + File.separator+ "controller" + File.separator + makeInfo.getClassname() + "Controller.java", classBuild.toString());
        return this;
    }

    private void annotationHandle(ClassBuild classBuild){
        AnnotationBuild controllerAnnotation = new AnnotationBuild(org.springframework.stereotype.Controller.class);
        AnnotationBuild allArgsConstructorAnnotation = new AnnotationBuild(AllArgsConstructor.class);
        AnnotationBuild requestMappingAnnotation = new AnnotationBuild(RequestMapping.class);
        requestMappingAnnotation.addParam("value", "/admin-" + makeInfo.getModuleName() + "/" + makeInfo.getIdentity());
        classBuild.addAnnotationClass(controllerAnnotation);
        classBuild.addAnnotationClass(allArgsConstructorAnnotation);
        classBuild.addAnnotationClass(requestMappingAnnotation);
        classBuild.addImportClass(org.springframework.stereotype.Controller.class);
        classBuild.addImportClass(AllArgsConstructor.class);
        classBuild.addImportClass(RequestMapping.class);
    }

    private void methodHandle(ClassBuild classBuild){
        listMethodHandle(classBuild);
        enumMapGetMethodHandle(classBuild);
    }

    private void enumMapGetMethodHandle(ClassBuild classBuild) {
        MethodBuild enumMapGetMethod = new MethodBuild("getEnumMap");
        enumMapGetMethod.addAnnotation(new AnnotationBuild(GetMapping.class).addParam("value", "get-enum-map"));
        enumMapGetMethod.setReturnType(new GenericTypeBuild(Response.class).addGeneric(
                new GenericTypeBuild(List.class).addGeneric(
                        new GenericTypeBuild(Map.class).addGeneric(String.class, Object.class)
                )
        ));
        enumMapGetMethod.addAnnotation(new AnnotationBuild(ResponseBody.class));
        MethodParamBuild name = new MethodParamBuild("name", new GenericTypeBuild(String.class));
        name.addAnnotation(new AnnotationBuild(RequestParam.class).addParam("value", "name"));
        enumMapGetMethod.addMethodParam(name);

        enumMapGetMethod.addCode("List<Map<String, Object>> enumMap = new ArrayList<>();");
        enumMap.forEach((key, value) -> {
            enumMapGetMethod.addCode(String.format("if (name.equals(\"%s\")) {", key));
            enumMapGetMethod.addCode(MasterMake.retraction(1) + String.format("enumMap = %sEntity.Status.getEnumList();", makeInfo.getClassname()));
            enumMapGetMethod.addCode("}");
        });
        classBuild.addImportClass(ResponseBody.class);
        classBuild.addImportClass(RequestParam.class);
        classBuild.addImportClass(ArrayList.class);
        classBuild.addImportClass(List.class);
        classBuild.addImportClass(Map.class);
        enumMapGetMethod.addCode("return Response.success(enumMap);");
        classBuild.addMethod(enumMapGetMethod);
    }

    private void listMethodHandle(ClassBuild classBuild){
        MethodBuild list = new MethodBuild("list");
        list.addAnnotation(new AnnotationBuild(GetMapping.class).addParam("value", "list"));
        list.setReturnType(new GenericTypeBuild(String.class));
        list.addMethodParam(new MethodParamBuild("model", new GenericTypeBuild(Model.class)));
        list.addCode(String.format("return \"%s/%s/list\";", makeInfo.getModuleName(), makeInfo.getIdentity()));
        classBuild.addMethod(list);
        classBuild.addImportClass(GetMapping.class);
        classBuild.addImportClass(Model.class);

        /*
          list-data
         */
        MethodBuild listData = new MethodBuild("listData");
        listData.addAnnotation(new AnnotationBuild(GetMapping.class).addParam("value", "list-data"));
        listData.addAnnotation(new AnnotationBuild(ResponseBody.class));
        GenericTypeBuild listDataReturnType = new GenericTypeBuild(Response.class);
        listDataReturnType.addGeneric(new GenericTypeBuild(List.class).addGeneric(
                new GenericTypeBuild(makeInfo.getClassname() + "Entity")
        ));
        listData.setReturnType(listDataReturnType);
        GenericTypeBuild paramType = new GenericTypeBuild(Map.class).addGeneric(String.class, Object.class);
        MethodParamBuild searchDTOParam = new MethodParamBuild("searchDTO", paramType);
        searchDTOParam.addAnnotation(new AnnotationBuild(RequestParam.class));
        listData.addMethodParam(searchDTOParam);

        listData.addCode(String.format("List<%s> list = %sService.getList(new DataAutoSearch(searchDTO));", makeInfo.getClassname() + "Entity", makeInfo.getIdentity()));
        listData.addCode("return Response.success(list);");

        classBuild.addMethod(listData);
        classBuild.addImportClass(ResponseBody.class);
        classBuild.addImportClass(RequestParam.class);
        classBuild.addImportClass(DataAutoSearch.class);
        classBuild.addImportClass(List.class);
        classBuild.addImportClass(Map.class);
        classBuild.addImportClass(Response.class);
        classBuild.addImportClass(makeInfo.getPackageName() + "." + makeInfo.getClassname() + "Entity");
    }


}
